import dpkt  # 推荐使用dpkt或scapy解析PCAP
from email.parser import BytesParser
import re
import hashlib
import json
import time
from datetime import datetime
from collections import defaultdict
import base64
import urllib.parse
import socket

class PcapAnalyzer:
    def __init__(self, pcap_path, bandwidth_interval=1):
        self.pcap_path = pcap_path
        self.bandwidth_interval = bandwidth_interval  # 带宽统计时间间隔（秒）
        # 优化敏感规则配置，更精确的匹配
        self.rules = {
            'secrets': [
                r'绝密[文件|信息|资料]?',
                r'机密[文件|信息|资料]?', 
                r'商业秘密',
                r'内部[文件|资料|信息]',
                r'保密[文件|资料]?',
                r'[\u4e00-\u9fa5]{2,10}密级'
            ],
            'keywords': [
                r'密码[：:]\s*[^\s]{6,20}',
                r'账号[：:]\s*[^\s]{3,20}',
                r'密钥[：:]\s*[^\s]{10,50}',
                r'身份证[号|号码][：:]\s*\d{18}',
                r'银行卡[号|号码][：:]\s*\d{16,19}',
                r'登录[名|账号][：:]\s*[^\s]{3,20}',
                r'admin[：:]\s*[^\s]{3,20}',
                r'root[：:]\s*[^\s]{3,20}'
            ],
            'patterns': [
                r'\b\d{18}[\sX]\b',         # 身份证（更精确）
                r'\b\d{16,19}\b',            # 银行卡（更精确）
                r'\b1[3-9]\d{9}\b',         # 手机号
                r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b',  # 邮箱
                r'\b[A-Za-z0-9+/]{20,}={0,2}\b',  # Base64（更严格）
                r'\b[a-fA-F0-9]{32}\b',     # MD5
                r'\b[a-fA-F0-9]{40}\b',     # SHA1
                r'\b[a-fA-F0-9]{64}\b'      # SHA256
            ]
        }
        # 会话追踪字典
        self.sessions = {}  # {(src_ip, src_port, dst_ip, dst_port): bytearray}
        # 分析结果存储
        self.analysis_results = {
            'alerts': [],
            'statistics': defaultdict(int),
            'sessions': [],
            'protocols': defaultdict(int),
            'detection_summary': defaultdict(int),  # 新增：检测类型统计
            'bandwidth_stats': [],  # 新增: 带宽统计
            'top_hosts': []  # 新增: Top N 通信主机
        }
        
        # 带宽和Top主机统计所需
        self.host_traffic = defaultdict(int)
        self.bandwidth_data = {}  # {timestamp_interval: bytes}

    def _tcp_session_tracker(self, ip, tcp):
        """重组TCP会话流"""
        key = (ip.src, tcp.sport, ip.dst, tcp.dport)
        reverse_key = (ip.dst, tcp.dport, ip.src, tcp.sport)
        
        # 处理分段报文
        if key not in self.sessions:
            self.sessions[key] = bytearray()
        self.sessions[key].extend(tcp.data)

        # 检查FIN/RST标志位
        if tcp.flags & (dpkt.tcp.TH_FIN | dpkt.tcp.TH_RST):
            return self.sessions.pop(key, None)
        return None

    def _is_text_content(self, data):
        """判断是否为文本内容"""
        try:
            text = data.decode('utf-8', errors='ignore')
            # 检查文本可读性
            printable_ratio = sum(1 for c in text if c.isprintable() or c.isspace()) / len(text)
            return printable_ratio > 0.7 and len(text) > 10
        except:
            return False

    def _extract_body(self, msg):
        """提取邮件/HTTP正文"""
        try:
            if msg.is_multipart():
                for part in msg.walk():
                    if part.get_content_type() == "text/plain":
                        return part.get_payload(decode=True).decode('utf-8', errors='ignore')
            else:
                return msg.get_payload(decode=True).decode('utf-8', errors='ignore')
        except Exception as e:
            print(f"正文提取错误: {e}")
            return ""

    def _get_attachments(self, msg):
        """处理邮件附件"""
        attachments = []
        try:
            if msg.is_multipart():
                for part in msg.walk():
                    if part.get_filename():
                        attachments.append({
                            'filename': part.get_filename(),
                            'content_type': part.get_content_type(),
                            'size': len(part.get_payload())
                        })
        except Exception as e:
            print(f"附件处理错误: {e}")
        return attachments

    def _parse_http(self, payload):
        """解析HTTP内容"""
        try:
            # 尝试解析HTTP请求/响应
            if payload.startswith(b'POST') or payload.startswith(b'GET'):
                # HTTP请求
                lines = payload.split(b'\r\n')
                if len(lines) > 0:
                    method, path, version = lines[0].decode('utf-8', errors='ignore').split(' ', 2)
                    
                    # 查找POST数据
                    body_start = payload.find(b'\r\n\r\n')
                    if body_start != -1:
                        body = payload[body_start + 4:]
                        # 只处理文本内容
                        if self._is_text_content(body):
                            return {
                                'type': 'http_request',
                                'method': method,
                                'path': path,
                                'body': body.decode('utf-8', errors='ignore')
                            }
            elif payload.startswith(b'HTTP/'):
                # HTTP响应
                lines = payload.split(b'\r\n')
                if len(lines) > 0:
                    version, status_code, status_text = lines[0].decode('utf-8', errors='ignore').split(' ', 2)
                    
                    body_start = payload.find(b'\r\n\r\n')
                    if body_start != -1:
                        body = payload[body_start + 4:]
                        # 只处理文本内容
                        if self._is_text_content(body):
                            return {
                                'type': 'http_response',
                                'status_code': status_code,
                                'body': body.decode('utf-8', errors='ignore')
                            }
        except Exception as e:
            print(f"HTTP解析错误: {e}")
        return None

    def _parse_email(self, data):
        """解析邮件内容"""
        try:
            msg = BytesParser().parsebytes(data)
            body = self._extract_body(msg)
            if body:  # 只处理有正文的邮件
                return {
                    'type': 'email',
                    'from': msg['from'],
                    'to': msg['to'],
                    'subject': msg['subject'],
                    'body': body,
                    'attachments': self._get_attachments(msg)
                }
        except Exception as e:
            print(f"邮件解析错误: {e}")
        return None

    def _get_snippet(self, content, pattern, context_length=30):
        """获取命中内容片段"""
        try:
            match = re.search(pattern, content, re.I)
            if match:
                start = max(0, match.start() - context_length)
                end = min(len(content), match.end() + context_length)
                snippet = content[start:end].replace('\n', ' ').strip()
                # 确保片段可读
                if len(snippet) > 10:
                    return snippet
        except Exception as e:
            print(f"片段提取错误: {e}")
        return ""

    def _content_analyzer(self, content):
        """深度内容分析引擎"""
        alerts = []
        if not content or len(content) < 10:
            return alerts
            
        # 文本检测（支持中文）
        for category, patterns in self.rules.items():
            for pattern in patterns:
                matches = re.finditer(pattern, content, re.I)
                for match in matches:
                    matched_text = match.group()
                    snippet = self._get_snippet(content, pattern)
                    
                    # 只记录有意义的匹配
                    if snippet and len(matched_text) > 3:
                        alerts.append({
                            'type': category,
                            'pattern': pattern,
                            'snippet': snippet,
                            'position': match.start(),
                            'matched_text': matched_text,
                            'description': self._get_detection_description(category, matched_text)
                        })
                        
                        # 统计检测类型
                        self.analysis_results['detection_summary'][category] += 1
        return alerts

    def _get_detection_description(self, category, matched_text):
        """获取检测描述"""
        descriptions = {
            'secrets': '涉密信息',
            'keywords': '敏感关键词',
            'patterns': '敏感数据模式'
        }
        
        if category == 'patterns':
            if re.match(r'\d{18}', matched_text):
                return '身份证号码'
            elif re.match(r'\d{16,19}', matched_text):
                return '银行卡号'
            elif re.match(r'1[3-9]\d{9}', matched_text):
                return '手机号码'
            elif '@' in matched_text:
                return '邮箱地址'
            elif re.match(r'[A-Za-z0-9+/]{20,}', matched_text):
                return 'Base64编码'
            elif re.match(r'[a-fA-F0-9]{32}', matched_text):
                return 'MD5哈希值'
            elif re.match(r'[a-fA-F0-9]{40}', matched_text):
                return 'SHA1哈希值'
            elif re.match(r'[a-fA-F0-9]{64}', matched_text):
                return 'SHA256哈希值'
        
        return descriptions.get(category, '未知类型')

    def _handle_protocol(self, transport, payload):
        """协议分发处理器（增强版）"""
        dport = transport.dport
        sport = transport.sport

        # HTTP (明文)
        if dport == 80 or sport == 80:
            if b"POST" in payload[:10] or b"GET" in payload[:10] or b"HTTP/" in payload[:10]:
                return self._parse_http(payload)

        # HTTPS (加密流量，仅识别协议)
        elif dport == 443 or sport == 443:
            return {'type': 'https'}

        # TLS/SSL (其他端口的加密流量)
        elif dport in [993, 995, 465, 587] or sport in [993, 995, 465, 587]:
            # 检查TLS握手特征
            if (len(payload) > 5 and payload[0] == 0x16 and 
                (payload[1:3] == b'\x03\x01' or payload[1:3] == b'\x03\x02' or payload[1:3] == b'\x03\x03')):
                return {'type': 'tls'}
            # 检查SSL特征
            elif (len(payload) > 5 and payload[0] == 0x16 and 
                  (payload[1:3] == b'\x03\x00' or payload[1:3] == b'\x02\x00')):
                return {'type': 'ssl'}

        # SSH
        elif dport == 22 or sport == 22:
            if b"SSH-" in payload[:10]:
                return {'type': 'ssh'}

        # SMTP
        elif dport in [25, 587, 465] or sport in [25, 587, 465]:
            # 简单的关键字检测，避免对加密SMTP流的错误解析
            if b"HELO" in payload or b"EHLO" in payload or b"MAIL FROM" in payload:
                email_result = self._parse_email(payload)
                if email_result:
                    email_result['type'] = 'smtp'
                    return email_result

        # POP3
        elif dport in [110, 995] or sport in [110, 995]:
            if b"+OK" in payload or b"USER" in payload or b"PASS" in payload:
                email_result = self._parse_email(payload)
                if email_result:
                    email_result['type'] = 'pop3'
                    return email_result

        # IMAP
        elif dport in [143, 993] or sport in [143, 993]:
            if b"CAPABILITY" in payload or b"LOGIN" in payload or b"AUTHENTICATE" in payload:
                email_result = self._parse_email(payload)
                if email_result:
                    email_result['type'] = 'imap'
                    return email_result

        # FTP
        elif dport == 21 or sport == 21:
            if b'USER ' in payload or b'PASS ' in payload:
                return {
                    'type': 'ftp',
                    'data': payload.decode('utf-8', errors='ignore')
                }

        # Telnet
        elif dport == 23 or sport == 23:
            if b'\xff\xfd' in payload or b'\xff\xfe' in payload or b'\xff\xff' in payload:
                return {'type': 'telnet'}

        # DNS
        elif dport == 53 or sport == 53:
            try:
                dns = dpkt.dns.DNS(payload)
                return {
                    'type': 'dns',
                    'queries': [q.name for q in dns.qd] if dns.qd else []
                }
            except:
                pass

        # DHCP
        elif dport == 67 or dport == 68 or sport == 67 or sport == 68:
            if len(payload) > 240 and payload[0] == 1:  # DHCP message type
                return {'type': 'dhcp'}

        # NTP
        elif dport == 123 or sport == 123:
            if len(payload) >= 48:  # NTP packet minimum size
                return {'type': 'ntp'}

        # SNMP
        elif dport == 161 or dport == 162 or sport == 161 or sport == 162:
            if payload.startswith(b'\x30'):  # ASN.1 sequence
                return {'type': 'snmp'}

        # LDAP
        elif dport == 389 or sport == 389:
            if payload.startswith(b'\x30'):  # ASN.1 sequence
                return {'type': 'ldap'}

        # LDAPS
        elif dport == 636 or sport == 636:
            return {'type': 'ldaps'}

        # RDP (Remote Desktop Protocol)
        elif dport == 3389 or sport == 3389:
            if b'RDP' in payload or payload.startswith(b'\x03\x00'):
                return {'type': 'rdp'}

        # VNC
        elif dport in [5900, 5901, 5902] or sport in [5900, 5901, 5902]:
            if b'RFB' in payload:
                return {'type': 'vnc'}

        # MySQL
        elif dport == 3306 or sport == 3306:
            if len(payload) > 4 and payload[4] in [0x01, 0x02, 0x03, 0x04, 0x05, 0x0a]:
                return {'type': 'mysql'}

        # PostgreSQL
        elif dport == 5432 or sport == 5432:
            if payload.startswith(b'\x00\x00\x00'):
                return {'type': 'postgresql'}

        # Redis
        elif dport == 6379 or sport == 6379:
            if payload.startswith(b'*') or payload.startswith(b'$') or payload.startswith(b'+'):
                return {'type': 'redis'}

        # MongoDB
        elif dport == 27017 or sport == 27017:
            if len(payload) > 16 and payload[0] in [0x80, 0x81, 0x82, 0x83, 0x84]:
                return {'type': 'mongodb'}

        # Memcached
        elif dport == 11211 or sport == 11211:
            if b'get ' in payload or b'set ' in payload or b'add ' in payload:
                return {'type': 'memcached'}

        # IRC
        elif dport in [6667, 6668, 6669] or sport in [6667, 6668, 6669]:
            if b'NICK ' in payload or b'JOIN ' in payload or b'PRIVMSG ' in payload:
                return {'type': 'irc'}

        # BitTorrent
        elif dport in [6881, 6882, 6883, 6884, 6885, 6886, 6887, 6888, 6889] or sport in [6881, 6882, 6883, 6884, 6885, 6886, 6887, 6888, 6889]:
            if b'\x13BitTorrent protocol' in payload:
                return {'type': 'bittorrent'}

        # SIP (VoIP)
        elif dport in [5060, 5061] or sport in [5060, 5061]:
            if b'SIP/' in payload or b'INVITE ' in payload or b'REGISTER ' in payload:
                return {'type': 'sip'}

        # RTSP
        elif dport == 554 or sport == 554:
            if b'RTSP/' in payload or b'DESCRIBE ' in payload or b'PLAY ' in payload:
                return {'type': 'rtsp'}

        # SMB/CIFS
        elif dport in [139, 445] or sport in [139, 445]:
            if payload.startswith(b'\xff\x53\x4d\x42') or payload.startswith(b'\xfe\x53\x4d\x42'):
                return {'type': 'smb'}

        # NFS
        elif dport == 2049 or sport == 2049:
            if payload.startswith(b'\x80\x00\x00\x28') or payload.startswith(b'\x80\x00\x00\x29'):
                return {'type': 'nfs'}

        # TFTP
        elif dport == 69 or sport == 69:
            if payload[0] in [0x00, 0x01, 0x02, 0x03, 0x04, 0x05]:
                return {'type': 'tftp'}

        # Syslog
        elif dport == 514 or sport == 514:
            if b'<' in payload and b'>' in payload:
                return {'type': 'syslog'}

        # NetBIOS
        elif dport == 137 or sport == 137:
            if payload.startswith(b'\x80\xf0\x00\x10'):
                return {'type': 'netbios'}

        # Kerberos
        elif dport == 88 or sport == 88:
            if payload.startswith(b'\x6a\x82') or payload.startswith(b'\x6b\x82'):
                return {'type': 'kerberos'}

        # LDAP over SSL
        elif dport == 636 or sport == 636:
            return {'type': 'ldaps'}

        # IMAPS
        elif dport == 993 or sport == 993:
            return {'type': 'imaps'}

        # POP3S
        elif dport == 995 or sport == 995:
            return {'type': 'pop3s'}

        # SMTPS
        elif dport == 465 or sport == 465:
            return {'type': 'smtps'}

        return None

    def _handle_ethernet_protocol(self, eth):
        """处理以太网层协议"""
        if eth.type == dpkt.ethernet.ETH_TYPE_IP:
            return 'ip'
        elif eth.type == dpkt.ethernet.ETH_TYPE_ARP:
            return 'arp'
        elif eth.type == dpkt.ethernet.ETH_TYPE_IP6:
            return 'ipv6'
        elif eth.type == 0x8100:  # VLAN
            return 'vlan'
        elif eth.type == 0x86dd:  # IPv6
            return 'ipv6'
        else:
            return 'ethernet_other'

    def _handle_ip_protocol(self, ip):
        """处理IP层协议"""
        if ip.p == dpkt.ip.IP_PROTO_TCP:
            return 'tcp'
        elif ip.p == dpkt.ip.IP_PROTO_UDP:
            return 'udp'
        elif ip.p == dpkt.ip.IP_PROTO_ICMP:
            return 'icmp'
        elif ip.p == dpkt.ip.IP_PROTO_IGMP:
            return 'igmp'
        elif ip.p == 6:  # TCP
            return 'tcp'
        elif ip.p == 17:  # UDP
            return 'udp'
        elif ip.p == 1:  # ICMP
            return 'icmp'
        elif ip.p == 2:  # IGMP
            return 'igmp'
        elif ip.p == 47:  # GRE
            return 'gre'
        elif ip.p == 50:  # ESP
            return 'esp'
        elif ip.p == 51:  # AH
            return 'ah'
        elif ip.p == 89:  # OSPF
            return 'ospf'
        elif ip.p == 103:  # PIM
            return 'pim'
        else:
            return f'ip_proto_{ip.p}'

    def _generate_alert(self, ip, tcp, result, alerts):
        """生成报警记录"""
        alert_record = {
            'timestamp': datetime.now().isoformat(),
            'src_ip': socket.inet_ntoa(ip.src),
            'dst_ip': socket.inet_ntoa(ip.dst),
            'src_port': tcp.sport,
            'dst_port': tcp.dport,
            'protocol': result.get('type', 'unknown'),
            'alerts': alerts,
            'content_preview': result.get('body', '')[:100] if result.get('body') else '',
            'detection_count': len(alerts)
        }
        
        self.analysis_results['alerts'].append(alert_record)
        self.analysis_results['statistics']['total_alerts'] += len(alerts)

    def analyze(self):
        """主分析循环"""
        with open(self.pcap_path, 'rb') as f:
            pcap = dpkt.pcap.Reader(f)
            
            for ts, buf in pcap:
                try:
                    # 更新带宽和Top主机统计
                    packet_len = len(buf)
                    timestamp_interval = int(ts / self.bandwidth_interval) * self.bandwidth_interval
                    self.bandwidth_data[timestamp_interval] = self.bandwidth_data.get(timestamp_interval, 0) + packet_len

                    eth = dpkt.ethernet.Ethernet(buf)
                    
                    # 识别以太网层协议
                    eth_protocol = self._handle_ethernet_protocol(eth)
                    self.analysis_results['protocols'][eth_protocol] += 1
                    
                    if not isinstance(eth.data, dpkt.ip.IP):
                        continue
                    
                    ip = eth.data
                    src_ip_str = socket.inet_ntoa(ip.src)
                    dst_ip_str = socket.inet_ntoa(ip.dst)
                    self.host_traffic[src_ip_str] += packet_len
                    self.host_traffic[dst_ip_str] += packet_len
                    self.analysis_results['statistics']['total_packets'] += 1
                    
                    # 识别IP层协议
                    ip_protocol = self._handle_ip_protocol(ip)
                    self.analysis_results['protocols'][ip_protocol] += 1
                    
                    if isinstance(ip.data, dpkt.tcp.TCP):
                        tcp = ip.data
                        self.analysis_results['statistics']['tcp_packets'] += 1
                        
                        # TCP会话重组
                        complete_data = self._tcp_session_tracker(ip, tcp)
                        if complete_data:
                            # 应用层协议处理
                            result = self._handle_protocol(tcp, bytes(complete_data))
                            if result:
                                self.analysis_results['protocols'][result['type']] += 1
                                
                                if 'body' in result and result['body']:
                                    # 内容分析
                                    alerts = self._content_analyzer(result['body'])
                                    if alerts:
                                        self._generate_alert(ip, tcp, result, alerts)
                        else:
                            # 对于未完成会话的数据包，尝试识别协议
                            if tcp.data:
                                result = self._handle_protocol(tcp, tcp.data)
                                if result:
                                    self.analysis_results['protocols'][result['type']] += 1
                                        
                    elif isinstance(ip.data, dpkt.udp.UDP):
                        udp = ip.data
                        self.analysis_results['statistics']['udp_packets'] += 1
                        
                        # UDP协议处理
                        result = self._handle_protocol(udp, udp.data)
                        if result:
                            self.analysis_results['protocols'][result['type']] += 1
                                
                    elif isinstance(ip.data, dpkt.icmp.ICMP):
                        icmp = ip.data
                        self.analysis_results['statistics']['icmp_packets'] = self.analysis_results['statistics'].get('icmp_packets', 0) + 1
                        self.analysis_results['protocols']['icmp'] += 1
                                
                except Exception as e:
                    print(f"数据包解析异常: {e}")
                    self.analysis_results['statistics']['error_packets'] += 1
        
        # 分析结束后，处理带宽和Top主机数据
        self._finalize_stats()

    def _finalize_stats(self):
        """在分析结束后，整理带宽和Top主机统计数据"""
        # 整理带宽数据
        for timestamp, total_bytes in sorted(self.bandwidth_data.items()):
            self.analysis_results['bandwidth_stats'].append({
                'time': datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S'),
                'bytes': total_bytes
            })

        # 整理Top主机数据
        sorted_hosts = sorted(self.host_traffic.items(), key=lambda item: item[1], reverse=True)
        self.analysis_results['top_hosts'] = [
            {'host': host, 'bytes': traffic} for host, traffic in sorted_hosts[:10]  # 取前10
        ]

    def get_results(self):
        """获取分析结果"""
        return self.analysis_results

    def save_results(self, filename):
        """保存分析结果到JSON文件"""
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(self.analysis_results, f, ensure_ascii=False, indent=2)

    def print_summary(self):
        """打印分析摘要"""
        results = self.get_results()
        print("\n=== 网络监控分析摘要 ===")
        print(f"📊 数据包统计:")
        print(f"   总数据包数: {results['statistics']['total_packets']}")
        print(f"   TCP包数: {results['statistics']['tcp_packets']}")
        print(f"   UDP包数: {results['statistics']['udp_packets']}")
        print(f"   ICMP包数: {results['statistics'].get('icmp_packets', 0)}")
        print(f"   错误包数: {results['statistics']['error_packets']}")
        
        print(f"\n🌐 协议分布:")
        # 按协议类型分组显示
        transport_protocols = ['tcp', 'udp', 'icmp', 'igmp']
        application_protocols = ['http', 'https', 'ssh', 'ftp', 'dns', 'dhcp', 'ntp', 'snmp', 'ldap', 'rdp', 'vnc', 'mysql', 'postgresql', 'redis', 'mongodb', 'memcached', 'irc', 'bittorrent', 'sip', 'rtsp', 'smb', 'nfs', 'tftp', 'syslog', 'netbios', 'kerberos', 'telnet', 'smtp', 'pop3', 'imap', 'smtps', 'pop3s', 'imaps', 'ldaps', 'tls', 'ssl']
        network_protocols = ['ip', 'arp', 'ipv6', 'vlan', 'ethernet_other']
        
        print("   传输层协议:")
        for protocol in transport_protocols:
            if protocol in results['protocols']:
                print(f"     {protocol.upper()}: {results['protocols'][protocol]}")
        
        print("   应用层协议:")
        for protocol in application_protocols:
            if protocol in results['protocols']:
                print(f"     {protocol.upper()}: {results['protocols'][protocol]}")
        
        print("   网络层协议:")
        for protocol in network_protocols:
            if protocol in results['protocols']:
                print(f"     {protocol.upper()}: {results['protocols'][protocol]}")
        
        # 显示其他未分类的协议
        other_protocols = [p for p in results['protocols'].keys() 
                          if p not in transport_protocols + application_protocols + network_protocols]
        if other_protocols:
            print("   其他协议:")
            for protocol in other_protocols:
                print(f"     {protocol.upper()}: {results['protocols'][protocol]}")
        
        print(f"\n🚨 安全检测:")
        print(f"   总告警数: {results['statistics']['total_alerts']}")
        for detection_type, count in results['detection_summary'].items():
            print(f"   {detection_type}: {count}")
        
        print(f"\n📋 告警详情:")
        for i, alert in enumerate(results['alerts'][:5]):  # 只显示前5个
            print(f"   {i+1}. {alert['protocol']} - {alert['src_ip']} -> {alert['dst_ip']}")
            for a in alert['alerts']:
                print(f"      - {a['description']}: {a['matched_text']}")
        
        print("\n📈 Top 10 通信主机 (按流量):")
        for i, host_data in enumerate(results['top_hosts']):
            print(f"   {i+1}. {host_data['host']}: {host_data['bytes'] / 1024:.2f} KB")
        
        print(f"\n📊 带宽统计:")
        if results['bandwidth_stats']:
            total_bytes = sum(item['bytes'] for item in results['bandwidth_stats'])
            print(f"   总流量: {total_bytes / 1024 / 1024:.2f} MB")
            print(f"   时间间隔数: {len(results['bandwidth_stats'])}")
            print(f"   平均每间隔流量: {total_bytes / len(results['bandwidth_stats']) / 1024:.2f} KB")
        else:
            print("   暂无带宽数据")

if __name__ == "__main__":
    analyzer = PcapAnalyzer("SnifferUI_20250514163247.pcap")
    analyzer.analyze()
    
    # 保存结果
    analyzer.save_results("analysis_results.json")
    
    # 打印摘要
    analyzer.print_summary()